import tensorflow as tf
import foolbox as fb
from keras import Sequential
from keras.layers import Dense
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import minmax_scale
from sklearn.metrics import accuracy_score


def read_total_data(DataFrame):
    feature = []
    label = []
    for row in range(len(DataFrame)):
        temp_feature = []
        for col in range(len(DataFrame.columns) - 1):
            temp_feature.append(DataFrame[DataFrame.columns[col]][row])
        feature.append(temp_feature)
        label.append(DataFrame[DataFrame.columns[len(DataFrame.columns) - 1]][row])
    return feature, label


# data = pd.read_csv("australian.dat", sep=" ", header=None)
data = pd.read_csv("data_encoder_2.csv")
# data = pd.read_excel("default of credit card clients.xls")
total_feature, total_label = read_total_data(data)
total_feature_01 = minmax_scale(total_feature)
total_label = minmax_scale(total_label)

feature = tf.constant(total_feature_01, dtype=tf.float32)
label = tf.constant(total_label, dtype=tf.int32)

# 替代模型
model = Sequential()
model.add(Dense(20, activation="LeakyReLU"))
model.add(Dense(int(20 / 2), activation="LeakyReLU"))
model.add(Dense(int(20 / 2), activation="LeakyReLU"))
model.add(Dense(2, activation="softmax"))

# 目标模型
model_O = Sequential()
model_O.add(Dense(20, activation="LeakyReLU"))
model_O.add(Dense(int(20 / 2), activation="LeakyReLU"))
model_O.add(Dense(1, activation="sigmoid"))

model_O.compile(loss='BinaryFocalCrossentropy', optimizer=tf.keras.optimizers.Adam(learning_rate=0.01))
model_O.fit(total_feature_01, total_label)

# 目标模型预测结果
label_predict = model_O.predict(total_feature_01)
label_predict = [item for list in label_predict for item in list]
label_predict = np.round(np.array(label_predict), 0)

# print("目标模型准确率:")
# print(accuracy_score(label_predict, total_label))

bounds = (-1, 1)
# bounds = (-0.001, 1.001)
fmodel = fb.TensorFlowModel(model, bounds=bounds)

# print(fb.utils.accuracy(fmodel, feature, label))

attack = fb.attacks.FGSM()

raw, clipped, is_adv = attack(fmodel, feature, label, epsilons=0.01)

# 不一定有对抗性，不一定在epsilons内
# print(raw)

# 不一定有对抗性，一定在epsilons内
# print(clipped)

# Ture的是对抗样本
# print(is_adv)

# 提取生成的对抗样本
adv_sample = clipped.numpy()
adv_index = is_adv.numpy()
adv_sample_feature = []
adv_samlpe_real_label = []
for i in range(len(adv_index)):
    if adv_index[i] == True:
        adv_sample_feature.append(adv_sample[i])
        adv_samlpe_real_label.append(total_label[i])

# 只要原始标签为1的对抗样本，并标记为0
adv_sample = []
for i in range(len(adv_samlpe_real_label)):
    if adv_samlpe_real_label[i] == 1:
        adv_sample.append(np.append(adv_sample_feature[i], 0))

new_data = pd.DataFrame(adv_sample)
new_data.to_csv('G_FGSM_data_german.csv',
                mode='a',
                header=False,
                float_format="%.5f",
                index=False
                )

# 对抗样本预测结果
'''adv_sample_feature = tf.constant(adv_sample_feature, dtype=tf.float32)
after_label_predict = model_O.predict(adv_sample_feature)
after_label_predict = [item for list in after_label_predict for item in list]
after_label_predict = np.round(np.array(after_label_predict), 0)
print("对抗样本预测准确率：")
print(accuracy_score(after_label_predict, adv_samlpe_real_label))'''

